package com.jkt.rms.commons.utils;

import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class StringUtils {
	
	private static final Pattern INTEGER_PATTERN = Pattern.compile( "\\-?[0-9]+" );
	private static final Pattern NUMBER_PATTERN = Pattern.compile( "\\-?[0-9]*\\.?[0-9]+" );
	private static Pattern pattern;
	private static Matcher matcher;

	private StringUtils() {
		// does nothing
	}
	
	
	/**
     * Trims a string of surrounding whitespace, allowing for null strings.
     *
     * @return the trimmed string or null
     */
    public static String trim( String value ) {
        if (value == null) {
            return null;
        }
        return value.trim();
    }
    
    /**
     * Extracts an integer from within a text string.
     */
    public static int parseIntFromText( String string ) {
        int s = 0;
        int n = string.length();
        while (s < n) {
            final char c = string.charAt( s );
            if (c == '+' || c == '-' || Character.isDigit( c )) {
                break;
            }
            s++;
        }
        int e = s;
        while (e < n) {
            final char c = string.charAt( e );
            if (c != '+' && c != '-' && !Character.isDigit( c )) {
                break;
            }
            e++;
        }
        if (s < e && e <= n) {
            return parseInt( string.substring( s, e ) );
        }
        throw new NumberFormatException( string );
    }
    
    /**
     * Enhances {@link Integer#parseInt(String)} to allow leading '+' sign.
     */
    public static int parseInt( String string ) {
        string = string.trim();
        if (string.charAt( 0 ) == '+') {
            string = string.substring( 1 );
        }
        return Integer.parseInt( string );
    }
    
    /**
     * Determines whether a string would be parseable as an integer.
     */
    public static boolean isInteger( CharSequence str ) {
        return str != null && INTEGER_PATTERN.matcher( str ).matches();
    }
    
    /**
     * Determines whether a string would be parseable as a number.
     */
    public static boolean isNumber( CharSequence str ) {
        return str != null && NUMBER_PATTERN.matcher( str ).matches();
    }

    /**
     * Determines whether a string consists entirely of letters and digits.
     */
    public static boolean isAlphaNumeric( final String s ) {
        if (s == null) {
            return false;
        }
        final char[] chars = s.toCharArray();
        for (int x = 0; x < chars.length; x++) {
            if ( !Character.isLetterOrDigit( chars[x] )) {
                return false;
            }
        }
        return true;
    }
    
    
    /**
     * Determines whether a string consists entirely digits.
     */
    public static boolean isDigit( final String s ) {
        if (s == null) {
            return false;
        }
        final char[] chars = s.toCharArray();
        for (int x = 0; x < chars.length; x++) {
            if ( !Character.isDigit( chars[x] )) {
                return false;
            }
        }
        return true;
    }
    
    
    /**
     * Implodes an array of strings into a single string.
     */
    public static String getDelimitedString( Collection<String> valueList, String delimiter ) {
        String actualDelimiter = "";
        final StringBuilder buffer = new StringBuilder();
        for (String string : valueList) {
            buffer.append( actualDelimiter ).append( string );
            actualDelimiter = delimiter;
        }
        return buffer.toString();
    }
    
    /**
     * Determines whether a string is non-blank. This requires that is is not null and that its
     * length is greater than zero.
     *
     * @param value
     *            the string under test
     * @return true if the string is not blank (and of course not null either)
     */
    public static boolean isNotEmptyString( CharSequence value ) {
        return value != null && value.length() > 0;
    }
    
    /**
     * Removes every double-quote mark from a string. If the string is null, null is returned.
     */
    public static String removeQuotes( String string ) {
        if (string != null && string.length() > 0) {
            string = string.replaceAll( "\"", "" ).trim();
        }
        return string;
    }
    
    /**
     * Determines whether a string consists entirely of letters.
     */
    public static boolean isAlpha( final String s ) {
        if (s == null) {
            return false;
        }
        final char[] chars = s.toCharArray();
        for (int x = 0; x < chars.length; x++) {
            if ( !Character.isLetter( chars[x] )) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Determines whether a string consists entirely of letters and white spaces.
     */
    public static boolean isAlphaWithSpace( final String s ) {
        if (s == null) {
            return false;
        }
        final char[] chars = s.toCharArray();
        for (int x = 0; x < chars.length; x++) {
        	if(Character.isSpaceChar(chars[x])) {
        		return true;
        	}
            if ( !Character.isLetter( chars[x] )) {
                return false;
            }
        }
        return true;
    }
    
    
    /**
     * Determines whether a string consists entirely of letters and single quote.
     */
	public static boolean isAlphabetAndSingleQuote(final String s) {
		final char[] chars = s.toCharArray();
		for (int x = 0; x < chars.length; x++) {
			if(Character.isLetter(chars[x])) {
				continue;
			}
			final char c = chars[x];
			if (c == '\'')
				continue; // numeric
			return false;
		}
		return true;
	}

	/**
     * Determines whether a string consists entirely of letters and hyphen.
     */
	public static boolean isAlphaNumericAndHyphen(final String s) {
		final char[] chars = s.toCharArray();
		for (int x = 0; x < chars.length; x++) {
			if(Character.isLetterOrDigit(chars[x])) {
				continue;
			} 
			final char c = chars[x];
			if(Character.isLetterOrDigit(chars[x])) {
				continue;
			}
			if (c == '-')
				continue; // hyphen
			return false;
		}
		return true;
	}
	
	/**
     * Determines whether a string is greater than by provided length.
     */
	public static boolean isGreaterThan(final String s, int lenParam) {
		if (s != null) {
			final int length = s.length();
			if (length > lenParam) {
				return false;
			}
		}
		return true;
	}

	/**
     * Determines whether a string matched with pattern.
     */
	public static boolean validate(final String str, final String strPattern) {
		pattern = Pattern.compile(strPattern);
		matcher = pattern.matcher(str);
		return matcher.matches();
	}
	
	/**
     * Determines whether a string field having valid phone no.
     */
	public static boolean validateContactNo(final String str) {
		final char[] chars = str.toCharArray();
		for (int x = 0; x < chars.length; x++) {
			final char c = chars[x];
			if(Character.isDigit(chars[x])) {
				continue;
			}
			if (c == ('-' | '+' | '.'))
				continue; // hyphen,+,.
			if (c != ' ')
				continue; // space
			return false;
		}
		return true;
	}
	
	/**
     * Determines whether a string consists entirely of letters and single quote and space.
     */
	public static boolean isAlphabetSingleQuoteAndSpace(final String s) {
		final char[] chars = s.toCharArray();
		for (int x = 0; x < chars.length; x++) {
			if(Character.isLetter(chars[x])) {
				continue;
			}else if(chars[x] == '\'' || chars[x] == ' '){
				continue;
			}
			return false;
		}
		return true;
	}
	
    /**
     * Determines whether a string consists entirely of letters and digits.
     */
    public static boolean isAlphaNumericWithSpace( final String s ) {
        if (s == null) {
            return false;
        }
        final char[] chars = s.toCharArray();
        for (int x = 0; x < chars.length; x++) {
            if ( Character.isLetterOrDigit( chars[x] ) || chars[x] == ' ') {
                continue;
            }
            return false;
        }
        return true;
    }
	
}
